﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;


public static class ExtenedMethods
{
    private static MD5CryptoServiceProvider m_md5Provider = new MD5CryptoServiceProvider();
    public static TValue Get<Tkey, TValue>(this Dictionary<Tkey, TValue> dict, Tkey key)
    {
        TValue value;
        dict.TryGetValue(key, out value);
        return value;
    }

    public static TValue GetDefault<TKey, TValue>(this Dictionary<TKey, TValue> dict, TKey key) where TValue : new()
    {
        TValue value;
        if (!dict.TryGetValue(key, out value))
        {
            value = new TValue();
            dict.Add(key, value);
        }
        return value;
    }

    public static void CopyTo<T>(this T[] arr, ref T[] tar) where T : PacketObject<T>
    {
        if (tar == null) tar = new T[arr.Length];
        else
        {
            PacketObject.BackArray(tar);
            Array.Resize(ref tar, arr.Length);
        }

        for (var i = 0; i < arr.Length; ++i) tar[i] = arr[i].Clone();
    }

    

    public static string GetMD5(this string str, bool upper = false)
    {
        var hash = m_md5Provider.ComputeHash(Encoding.Default.GetBytes(str));

        var md5 = "";
        for (var i = 0; i < hash.Length; ++i)
            md5 += hash[i].ToString(upper ? "X" : "x").PadLeft(2, '0');

        return md5;
    }


    public static Task<TResult> FromAsync<TArg1, TArg2, TArg3, TArg4, TResult>(
        this TaskFactory factory,
        Func<TArg1, TArg2, TArg3, TArg4, AsyncCallback, object, IAsyncResult> beginMethod,
        Func<IAsyncResult, TResult> endMethod,
        TArg1 arg1,
        TArg2 arg2,
        TArg3 arg3,
        TArg4 arg4,
        object state,
        TaskCreationOptions creationOptions = TaskCreationOptions.None,
        TaskScheduler scheduler = null)
    {
        scheduler = scheduler ?? TaskScheduler.Current;
        AsyncCallback callback = null;
        if (beginMethod == null)
        {
            throw new ArgumentNullException("beginMethod");
        }
        if (endMethod == null)
        {
            throw new ArgumentNullException("endMethod");
        }
        TaskCompletionSource<TResult> tcs =
             new TaskCompletionSource<TResult>(state, creationOptions);
        try
        {
            if (callback == null)
            {
                callback = delegate (IAsyncResult iar)
                {
                    tcs.TrySetResult(endMethod(iar));
                };
            }
            beginMethod(arg1, arg2, arg3, arg4, callback, state);
        }
        catch
        {
            tcs.TrySetResult(default(TResult));
            throw;
        }
        return tcs.Task;
    }

}
